package trb.complexshield.benchmarking;

import java.util.ArrayList;
import java.util.List;
import javax.media.j3d.BranchGroup;
import no.hrp.hvrc.rad.dosim.bvh.BottumUpBVH;
import no.hrp.hvrc.utils.j3d.BBox;
import no.hrp.hvrc.utils.j3d.Mat4;
import no.hrp.hvrc.utils.j3d.ObjectViewer;
import no.hrp.hvrc.utils.j3d.SGUtils;
import no.hrp.hvrc.utils.j3d.Vec3;
import no.hrp.hvrc.utils.j3d.boundingbox.BoundingBoxHelper;
import trb.complexshield.ComplexShield;
import trb.complexshield.bool.ComplexShieldSegmentsProducer;
import trb.complexshield.bool.model.AABBCreator;
import trb.complexshield.bool.model.BoolBox;
import trb.complexshield.bool.model.BoolOr;
import trb.complexshield.bool.model.BoolSubtract;
import trb.complexshield.bool.model.DistanceCreator;
import trb.complexshield.bool.model.SegmentsCreator;
import trb.complexshield.bool.visualisation.DistanceVisualisation;
import trb.complexshield.bool.visualisation.VisualisationUtils;
import trb.complexshield.closedmesh.BvhCollisionMesh;
import trb.complexshield.closedmesh.ClosedMesh;
import trb.complexshield.voxel.VoxelFromBool;
import trb.complexshield.voxel.VoxelGrid;
import trb.complexshield.voxel.VoxelGridBox;
import trb.complexshield.voxel.VoxelVisualisation;

public class BenchmarkRooms {

    private static final String MODEL_PATH = "./data/rooms.wrl";

    public static void main(String[] args) {
        try {
            Object boolModel = createBoolModel();
            float scale = 5;
            VoxelGridBox voxelGridBox = VoxelFromBool.createVoxel(boolModel, new VoxelGrid(Math.round(17*scale), Math.round(3.5f*scale), Math.round(11*scale)));
            //VoxelGridBox voxelGridBox = VoxelFromBool.createVoxel(boolModel, 30, 1);
            DistanceVisualisation distanceVisualisation = new DistanceVisualisation(
                    AABBCreator.createAABB(boolModel),
                    DistanceCreator.createDistanceProducer(boolModel));

            BranchGroup java3DModel = createJava3DModel();
            VisualisationUtils.toWireframe(java3DModel);
            BranchGroup branchGroup = SGUtils.wrapInBrancGroup(
                    //distanceVisualisation.update()
                    java3DModel
                    , new VoxelVisualisation(voxelGridBox, boolModel).rootBG
            );

            ObjectViewer.view(branchGroup);
        } catch (Exception ex) {
            ex.printStackTrace();
            System.exit(0);
        }
    }

    public static ComplexShield createBool() {
        Object boolModel = createBoolModel();
        BottumUpBVH.AABB aabb = new BottumUpBVH.AABB(AABBCreator.createAABB(boolModel));
        return new ComplexShieldSegmentsProducer(SegmentsCreator.createSegmentsProducer(boolModel), aabb);
    }

    public static Object createBoolModel() {
        List<BoolBox> subtractList = new ArrayList<>();
        float[] centerxs = {-6.3f, -2.1f, 2.1f, 6.3f};
        for (float centerx : centerxs) {
            subtractList.add(BoolBox.fromCenterAndSize(new Vec3(centerx, 1.5f, -3.2f), new Vec3(4, 3, 4), new Mat4()));
            subtractList.add(BoolBox.fromCenterAndSize(new Vec3(centerx, 1f, -1.1f), new Vec3(1, 2, 0.201f), new Mat4()));

            subtractList.add(BoolBox.fromCenterAndSize(new Vec3(centerx, 1.5f, 3.2f), new Vec3(4, 3, 4), new Mat4()));
            subtractList.add(BoolBox.fromCenterAndSize(new Vec3(centerx, 1f, 1.1f), new Vec3(1, 2, 0.201f), new Mat4()));
        }
        subtractList.add(BoolBox.fromCenterAndSize(new Vec3(0f, 1.5f, 0f), new Vec3(16.6f, 3, 2f), new Mat4()));

        subtractList.add(BoolBox.fromCenterAndSize(new Vec3(-8.4f, 1f, 0f), new Vec3(0.201f, 2, 1f), new Mat4()));
        subtractList.add(BoolBox.fromCenterAndSize(new Vec3(8.4f, 1f, 0f), new Vec3(0.201f, 2, 1f), new Mat4()));

        BoolBox outer = BoolBox.fromCenterAndSize(new Vec3(0, 1.5f, 0f), new Vec3(17f, 3.4f, 10.8f), new Mat4());
        BoolOr subtractOr = new BoolOr(subtractList.toArray(new BoolBox[0]));
        return new BoolSubtract(outer, subtractOr);
    }

    public static BranchGroup createJava3DModel() {
        return BenchmarkTub.loadVrml(MODEL_PATH).getSceneGroup();
    }

    public static ClosedMesh createClosedMesh() {
        return BenchmarkTub.createClosedMesh(createJava3DModel());
    }

    public static BvhCollisionMesh createBvhMesh() {
        return BenchmarkTub.createBvhMesh(createJava3DModel());
    }

    public static BBox getBBox() {
        return new BBox(BoundingBoxHelper.getBoundingBox(createJava3DModel()));
    }
}
